home *** CD-ROM | disk | FTP | other *** search
Text File | 1987-07-06 | 54.7 KB | 2,213 lines |
- Path: uunet!rs
- From: rs@uunet.UU.NET (Rich Salz)
- Newsgroups: comp.sources.unix
- Subject: v10i039: Interpreted Functional Programming lanuage, Part 06/07
- Message-ID: <579@uunet.UU.NET>
- Date: 7 Jul 87 23:23:00 GMT
- Organization: UUNET Communications Services, Arlington, VA
- Lines: 2202
- Approved: rs@uunet.uu.net
-
- Mod.sources: Volume 10, Number 39
- Submitted by: robison@b.cs.uiuc.edu (Arch Robison)
- Archive-name: ifp/Part06
-
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh.
- # The following files will be created:
- # interp/infun.c
- # interp/inimport.c
- # interp/inob.c
- # interp/inob.h
- # interp/list.c
- # interp/main.c
- # interp/node.c
- # interp/node.h
- export PATH; PATH=/bin:$PATH
- mkdir interp
- if test -f 'interp/infun.c'
- then
- echo shar: over-writing existing file "'interp/infun.c'"
- fi
- cat << \SHAR_EOF > 'interp/infun.c'
-
- /****** infun.c *******************************************************/
- /** **/
- /** University of Illinois **/
- /** **/
- /** Department of Computer Science **/
- /** **/
- /** Tool: IFP Version: 0.5 **/
- /** **/
- /** Author: Arch D. Robison Date: May 1, 1985 **/
- /** **/
- /** Revised by: Arch D. Robison Date: Aug 4, 1986 **/
- /** **/
- /** Principal Investigators: Prof. R. H. Campbell **/
- /** Prof. W. J. Kubitz **/
- /** **/
- /** **/
- /**------------------------------------------------------------------**/
- /** (C) Copyright 1987 University of Illinois Board of Trustees **/
- /** All Rights Reserved. **/
- /**********************************************************************/
-
-
- #include <stdio.h>
- #include <ctype.h>
- #include "struct.h"
- #include "node.h"
- #include "string.h"
- #include "inob.h"
-
- /*
- * PATTERN should be 0. Setting it to 1 enables a parser extension
- * for experimental compiler work.
- */
- #define PATTERN 0
-
- /*
- * MakeForm
- *
- * If correct, create form with node N and function list Funs.
- *
- * Output
- * result = 1 if no error, 0 otherwise
- */
- boolean MakeForm (Correct,N,Funs,InOut)
- boolean Correct;
- NodePtr N;
- ListPtr Funs;
- ObjectPtr InOut;
- {
- #ifdef PARAMBUG /* cure for CRAY C-compiler bug (see struct.h) */
- {
- ListPtr T = Funs;
- NewList (&T,1L);
- Funs = T;
- }
- #else
- NewList (&Funs,1L);
- #endif
- if (SysError || !Correct) {
- DelLPtr (Funs);
- return 0;
- } else {
- Funs->Val.Tag = NODE;
- Funs->Val.Node = CopyNPtr (N);
- RepTag (InOut,LIST);
- InOut->List = Funs;
- return 1;
- }
- }
-
- /*
- * InNext
- *
- * Input next composition, which should be followed by Token.
- *
- * Input
- * *F = input
- * End = pointer to MetaPtr to end of list.
- * Token = token expected.
- * K = pointer to entry of form being parsed
- */
- boolean InNext (F,End,Token,K,Env)
- InDesc *F;
- MetaPtr *End;
- char *Token;
- FormEntry *K;
- ListPtr Env;
- {
- NewList (*End,1L);
- if (SysError || !InComp (F,&(**End)->Val,Env)) return 0;
- if (!IsTok (F,Token)) {
- char Error [80];
- extern char *sprintf();
- (void) sprintf (Error,"'%s' part of '%s' expected",
- Token,K->FormComment);
- return InError (F,Error);
- }
- *End = &(**End)->Next;
- return 1;
- }
-
- /*
- * InPFO
- *
- * Input a PFO.
- *
- * Input
- * F = input descriptor pointing to 1st token after 1st keyword of form
- * K = index of form
- * Env = environment list
- *
- * Output
- * InOut = form
- */
- private boolean InPFO (F,InOut,K,Env)
- register InDesc *F;
- ObjectPtr InOut;
- FormEntry *K;
- ListPtr Env;
- {
- ListPtr R = NIL;
- MetaPtr A = &R;
- boolean Correct;
-
- switch (K-FormTable) {
- case NODE_If:
- Correct = 0;
- if (InNext (F,&A,"THEN",K,Env) && InNext (F,&A,"\0",K,Env))
- if (IsTok (F,"ELSIF")) {
- NewList (A,1L);
- Correct = !SysError && InPFO (F,&(*A)->Val,K,Env);
- } else
- if (IsTok (F,"ELSE")) Correct = InNext (F,&A,"END",K,Env);
- else (void) InError (F,"'ELSE' or 'ELSIF' expected");
- break;
-
- case NODE_Each:
- case NODE_RInsert:
- case NODE_Filter:
- Correct = InNext (F,&A,"END",K,NIL);
- break;
-
- case NODE_While:
- Correct = InNext (F,&A,"DO",K,NIL) && InNext (F,&A,"END",K,NIL);
- break;
- #if XDEF
- case NODE_XDef: {
- ListPtr OldEnv = Env;
- Correct = 0;
- NewList (A,1L);
- if (SysError || !InLHS (F,&(*A)->Val,&Env)) break;
- if (!IsTok (F,":=")) (void) InError (F,"':=' expected");
- else {
- A = &(*A)->Next;
- if (!InNext (F,&A,"}",K,OldEnv)) break;
- NewList (A,1L);
- if (InSimple (F,&(*A)->Val,Env)) Correct = 1;
- }
- break;
- }
- #endif
- case NODE_C:
- NewList (A,1L);
- if (Correct = !SysError && InObject (F,&(*A)->Val))
- if ((*A)->Val.Tag == BOTTOM) {
- /* Convert #? to #(null) */
- DelLPtr (R);
- R = NIL;
- }
- break;
-
- case NODE_Cons:
- if (!(Correct = IsTok (F,"]"))) {
- while ((Correct = InNext (F,&A,"\0",K,Env)) && IsTok (F,","))
- continue;
- if (Correct)
- if (Correct = IsTok (F,"]"));
- else (void) InError (F,"']' or ',' expected");
- }
- break;
-
- #if FETCH
- case NODE_Fetch:
- #endif
- case NODE_Out:
- NewList (A,1L);
- Correct = !SysError && InObject (F,&(*A)->Val);
- break;
-
- }
- return MakeForm (Correct,K->FormNode,R,InOut);
- }
-
- /*
- * InSelector
- *
- * Input
- * F = input descriptor pointing to selector
- *
- * Output
- * InOut = selector PFO
- */
- private boolean InSelector (F,InOut)
- register InDesc *F;
- ObjectPtr InOut;
- {
- register ListPtr P;
- long Index = 0;
-
- do
- Index = 10*Index + (*F->InPtr++) - '0';
- while isdigit (*F->InPtr);
-
- RepTag (InOut,LIST);
- InOut->List = NIL;
- NewList (&InOut->List,2L);
- if (SysError) {
- InOut->Tag = BOTTOM;
- return 0;
- }
- P = InOut->List;
- P->Val.Tag = NODE;
- P->Val.Node = FormTable [NODE_Sel].FormNode;
- P = P->Next;
- P->Val.Tag = INT;
- P->Val.Int = IsTok (F,"r") ? -Index : Index;
- return 1;
- }
-
- /*
- * InSimple
- *
- * Read a simple function
- *
- * Output
- * result = 1 iff error occurs, 0 otherwise
- * InOut = simple function if no error
- *
- * A SysError may occur, in which case InOut is unchanged.
- */
- boolean InSimple (F,InOut,Env)
- InDesc *F;
- ObjectPtr InOut;
- ListPtr Env;
- {
- static char InFirst[] = { /* First characters of InPrefix */
- 'I','E','W','#','[','F','@'
- #if FETCH
- ,'^'
- #endif
- #if XDEF
- ,'{'
- #endif
- ,'\0'
- };
- register FormEntry *K;
- extern char *index ();
-
- if (Debug & DebugParse) {
- printf ("InSimple: Env = "); OutList (Env);
- printf (", F = %s\n",F->InPtr);
- }
- InBlanks (F);
- #ifdef PATTERN
- if (IsTok (F,"!")) return InObject (F,InOut);
- #endif
- /*
- * The "index" lookup below quickly rejects strings which
- * cannot be key words.
- */
- if (NULL != index (InFirst,*F->InPtr)) {
- for (K=FormTable; K < ArrayEnd(FormTable); K++)
- if (*K->FormInPrefix != '\0' && IsTok (F,K->FormInPrefix))
- return InPFO (F,InOut,K,Env);
- } else
- if (isdigit (*F->InPtr))
- return InSelector (F,InOut);
-
- if (!InNode (F,InOut,Env))
- return 0;
- else if (InOut->List == NULL)
- return InError (F,"'/' not a function");
- else
- return 1;
- }
-
- /*
- * InComp
- *
- * Input a composition
- */
- boolean InComp (F,InOut,Env)
- register InDesc *F;
- ObjectPtr InOut;
- ListPtr Env;
- {
- Object X;
-
- if (Debug & DebugParse) {
- printf ("InComp: Env = ");
- OutList (Env);
- printf (", F = %s\n",F->InPtr);
- }
- X.Tag = BOTTOM;
- if (!InSimple (F,&X,Env)) return 0;
- else {
- InBlanks (F);
- if (!IsTok (F,"|")) {
- RepObject (InOut,&X);
- RepTag (&X,BOTTOM);
- return !SysError;
- } else {
- ListPtr P,R=NIL;
- boolean Correct;
- NewList (&R,1L);
- if (SysError) Correct = 0;
- else {
- CopyObject (&(P=R)->Val,&X);
- RepTag (&X,BOTTOM);
- do {
- NewList (&P->Next,1L);
- Correct = !SysError && InSimple (F,&(P=P->Next)->Val,NIL);
- InBlanks (F);
- } while (Correct && IsTok (F,"|"));
- }
- return MakeForm (Correct,FormTable[NODE_Comp].FormNode,R,InOut);
- }
- }
- }
-
- /*
- * InDef
- *
- * Input a function definition
- *
- * Input
- * FunName = Name of function
- * Output
- * InOut = function definition
- * result = 1 iff successful, 0 otherwise
- */
- boolean InDef (F,FunName,InOut)
- register InDesc *F;
- StrPtr FunName;
- ObjectPtr InOut;
- {
- Object Fun,S;
-
- Fun.Tag = BOTTOM;
- S.Tag = BOTTOM;
- F->InDefFun = FunName;
-
- InBlanks (F);
- if (!IsTok (F,"DEF")) return InError (F,"DEF expected");
- else {
- InBlanks (F);
- (void) InString (F,&S,NodeDelim,0);
- if (StrComp (S.String,FunName))
- (void) InError (F,"Definition name wrong");
- else {
- InBlanks (F);
- if (!IsTok (F,"AS")) (void) InError (F,"AS expected");
- else {
- InBlanks (F);
- if (InComp (F,&Fun,NIL)) {
- InBlanks (F);
- if (!IsTok (F,";")) (void) InError (F,"semicolon expected");
- else {
- InBlanks (F);
- if (*F->InPtr) (void) InError (F,"end of file expected");
- else {
- RepTag (&S,BOTTOM);
- CopyObject (InOut,&Fun);
- RepTag (&Fun,BOTTOM);
- return 1;
- }
- }
- }
- }
- }
- }
- RepTag (&S,BOTTOM);
- RepTag (&Fun,BOTTOM);
- return 0;
- }
-
-
- /********************************** infun.c **********************************/
-
- SHAR_EOF
- if test -f 'interp/inimport.c'
- then
- echo shar: over-writing existing file "'interp/inimport.c'"
- fi
- cat << \SHAR_EOF > 'interp/inimport.c'
-
- /****** inimport.c ****************************************************/
- /** **/
- /** University of Illinois **/
- /** **/
- /** Department of Computer Science **/
- /** **/
- /** Tool: IFP Version: 0.5 **/
- /** **/
- /** Author: Arch D. Robison Date: May 1, 1985 **/
- /** **/
- /** Revised by: Arch D. Robison Date: Oct 28, 1985 **/
- /** **/
- /** Principal Investigators: Prof. R. H. Campbell **/
- /** Prof. W. J. Kubitz **/
- /** **/
- /** **/
- /**------------------------------------------------------------------**/
- /** (C) Copyright 1987 University of Illinois Board of Trustees **/
- /** All Rights Reserved. **/
- /**********************************************************************/
-
-
- #include <stdio.h>
- #include <ctype.h>
- #include "struct.h"
- #include "node.h"
- #include "string.h"
- #include "inob.h"
-
- /*
- * DoubleDot
- *
- * Append a ".." to path list by deleting last element.
- *
- * Input
- * *F = file descriptor
- * *C = pointer to path list
- *
- * Output
- * result = pointer to last null field, null if error.
- */
- MetaPtr DoubleDot (F,C)
- InDesc *F;
- register MetaPtr C;
- {
- register MetaPtr A;
-
- if (*C == NULL) {
- (void) InError (F,"Too many ..'s.");
- return NULL;
- } else { /* Remove last element from path list R */
- do {
- A = C;
- C = &(*A)->Next;
- } while (*C != NULL);
- DelLPtr (*A);
- *A = NULL;
- return A;
- }
- }
-
- /*
- * NodeDelim is the set of pathname delimiters. Note that '>' and '<' are not
- * in the set since they are (perversely) legal function names.
- */
- char NodeDelim[] = " ,[](){}|;:/\t\n";
-
- /*
- * InNode
- *
- * Input a path. A path may represent a module, function, or functional
- * variable. Local functions are linked if possible to save time and space.
- *
- * The EBNF production definition for a node is:
- *
- * ["/"] string { "/" (string | "..") }
- *
- * Input
- * *F = input descriptor pointing to path
- * Env = environment
- *
- * Output
- * InOut = node (path list or node format) or functional variable (string)
- * *F = input descriptor pointing to next token after path
- *
- * A SysError may occur, in which case InOut is unchanged.
- */
- boolean InNode (F,InOut,Env)
- InDesc *F;
- ObjectPtr InOut;
- ListPtr Env;
- {
- ListPtr R = NULL; /* path list accumulator */
- register MetaPtr A = &R; /* pointer to Next field at end of accumulator */
- register NodePtr N;
- boolean FirstSlash;
-
- if (Debug & DebugParse) printf ("InNode: '%s'",F->InPtr);
- if (!(FirstSlash = *F->InPtr == '/')) {
-
- if (IsTok (F,"..")) {
- if (F->InDefMod != NULL) R = MakePath (F->InDefMod);
- if (NULL == (A = DoubleDot (F,&R))) goto Error;
- } else {
-
- Object S; /* relative path */
- S.Tag = BOTTOM;
- if (NULL == InString (F,&S,NodeDelim,0)) {
- if (!SysError) (void) InError (F,"path expected");
- goto Error;
- }
- if (!IsTok (F,"/")) {
-
- for (; Env!=NULL; Env=Env->Next)
- if (ObEqual (&Env->Val,&S)) {
- RepObject (InOut,&Env->Val); /* functional variable */
- return 1;
- }
-
- N = FindNode (F->InDefMod,S.String); /* local function */
- if (N != NULL) {
- if (N->NodeType == IMPORT) {
-
- /* Imported function - resolve alias */
- RepObject (InOut,&N->NodeData.NodeImp.ImpDef);
-
- } else { /* Local function already linked */
-
- RepTag (InOut,NODE);
- InOut->Node = CopyNPtr (N);
- }
- RepTag (&S,BOTTOM);
- return 1;
- }
- }
- if (F->InDefMod != NULL) R = MakePath (F->InDefMod);
- while (*A != NULL) A = &(*A)->Next;
- NewList (A,1L);
- (*A)->Val.Tag = STRING;
- (*A)->Val.String = S.String;
- }
- }
-
- while (IsTok (F,"/")) {
- if (IsTok (F,".."))
- if (NULL == (A = DoubleDot (F,&R))) return 0;
- else continue;
- else {
- NewList (A,1L);
- if (SysError) goto Error;
- if (NULL == InString (F,&(*A)->Val,NodeDelim,0)) {
- if (SysError) goto Error;
- else if (*F->InPtr != '/' && FirstSlash) {
- (void) DoubleDot (F,&R);
- break;
- } else {
- (void) InError (F,"Invalid path name");
- goto Error;
- }
- }
- A = &(*A)->Next;
- }
- FirstSlash = 0;
- }
-
- RepTag (InOut,LIST);
- InOut->List = R;
- return 1;
-
- Error:
- DelLPtr (R);
- return 0;
- }
-
- /*
- * InImport
- *
- * Input from an import file.
- *
- * An import file has the following format:
- *
- * { 'FROM' path 'IMPORT' string {,string} ';' }
- *
- * Input
- * F = input
- * M = pointer to module node
- */
- void InImport (F,M)
- register InDesc *F;
- register NodePtr M;
- {
- Object Path,Def;
- register NodePtr N;
- MetaPtr A;
-
- F->InDefFun = NULL;
- Path.Tag = BOTTOM;
- Def.Tag = BOTTOM;
-
- while (*F->InPtr) {
-
- if (!IsTok (F,"FROM")) {
- (void) InError (F,"FROM expected");
- break;
- }
-
- (void) InNode (F,&Path,NIL);
- if (!IsTok (F,"IMPORT")) {
- (void) InError (F,"IMPORT expected");
- break;
- }
-
- while (1) {
-
- if (NULL == InString (F,&Def," ,;\n",0)) {
- if (!SysError) (void) InError (F,"function name expected");
- goto Return;
- }
-
- N = MakeChild (M,Def.String);
-
- switch (N->NodeType) {
-
- case IMPORT:
- (void) InError (F,"duplicate imported identifier");
- break;
-
- case DEF:
- if (N->NRef > 1) {
- (void) InError (F,"identifies function elsewhere");
- break;
- } /* else continue on down to NEWNODE */
-
- case NEWNODE: {
- extern MetaPtr MakeCopy ();
- N->NodeType = IMPORT;
- N->NodeData.NodeImp.ImpDef.Tag = LIST;
- A = MakeCopy (&N->NodeData.NodeImp.ImpDef.List, Path.List);
- NewList (A,1L);
- RepObject (&(*A)->Val,&Def);
- break;
- }
- }
-
- if (IsTok (F,";")) break;
- if (!IsTok (F,",")) {
- (void) InError (F,"comma or semicolon expected");
- goto Return;
- }
- }
- }
- Return:
- RepTag (&Path,BOTTOM);
- RepTag (&Def,BOTTOM);
- return;
- }
-
-
- /******************************* inimport.c *******************************/
-
- SHAR_EOF
- if test -f 'interp/inob.c'
- then
- echo shar: over-writing existing file "'interp/inob.c'"
- fi
- cat << \SHAR_EOF > 'interp/inob.c'
-
- /****** inob.c ********************************************************/
- /** **/
- /** University of Illinois **/
- /** **/
- /** Department of Computer Science **/
- /** **/
- /** Tool: IFP Version: 0.5 **/
- /** **/
- /** Author: Arch D. Robison Date: May 1, 1985 **/
- /** **/
- /** Revised by: Arch D. Robison Date: Aug 6, 1986 **/
- /** **/
- /** Principal Investigators: Prof. R. H. Campbell **/
- /** Prof. W. J. Kubitz **/
- /** **/
- /** **/
- /**------------------------------------------------------------------**/
- /** (C) Copyright 1987 University of Illinois Board of Trustees **/
- /** All Rights Reserved. **/
- /**********************************************************************/
-
- /*************** object input parser (recursive descent) ***************/
-
-
- #include <stdio.h>
- #include <ctype.h>
- #include "struct.h"
- #include "node.h"
- #include "string.h"
- #include "inob.h"
-
- /*
- * ObDelim
- *
- * Theses characters delimit objects.
- * Compare with NodeDelim in inimport.c
- */
- private char ObDelim[] = " ,<>|[](){};:\t\n";
-
- /*
- * InBlanks
- *
- * Skip to first non-blank character not in comment.
- *
- * Input
- * F = input descriptor
- *
- * Output
- * F = input descriptor pointing to non-blank character
- */
- void InBlanks (F)
- register InDesc *F;
- {
- while (1) {
-
- while (1) {
- if (!*F->InPtr)
- if (F->InLineNum >= 0)
- if (NULL != fgets (F->InBuf,INBUFSIZE,F->InFile)) {
- F->InPtr = F->InBuf;
- F->InLineNum++;
- }
- if (!isspace (*F->InPtr)) break;
- F->InPtr++;
- }
-
- if (*F->InPtr == '(' && F->InPtr[1] == '*') {
- F->ComLevel++;
- F->InPtr+=2;
- } else if (*F->InPtr == '*' && F->InPtr[1] == ')') {
- F->ComLevel--;
- F->InPtr+=2;
- } else if (F->ComLevel && *F->InPtr) F->InPtr++;
- else break;
- }
- }
-
- /*
- * IsTok
- *
- * Check if next token in input is S. Skip if found.
- */
- boolean IsTok (F,S)
- InDesc *F;
- register char *S;
- {
- register char *T;
-
- for (T = F->InPtr; *S; S++,T++)
- if (*S != *T) return 0;
-
- /* Check if alphabetic token is prefix of longer token */
- if (isalpha (T[-1]) && isalpha (T[0])) return 0;
-
- F->InPtr = T;
- InBlanks (F);
- return 1;
- }
-
- /*
- * InString
- *
- * Input a string.
- *
- * Input
- * *F = input descriptor pointing to first character of string
- * Delim = string of non-alphanumeric delimiters
- * Quoted = skip closing delimiter
- *
- * Output
- * *F = input descriptor pointing to next token after string
- * X = string object
- * result = pointer to string, NULL if SysError or empty string.
- *
- * A SysError may occur, in which case X = bottom.
- */
- StrPtr InString (F,X,Delim,Quoted)
- register InDesc *F;
- ObjectPtr X;
- char *Delim;
- boolean Quoted;
- {
- CharPtr U;
- register char C;
-
- RepTag (X,STRING);
- X->String = NULL;
- CPInit (&U,&X->String);
- do {
- extern char *index ();
- C = *F->InPtr++;
- if (!isalnum (C) && NULL != index (Delim,C)) C = '\0';
- CPAppend (&U,C);
- if (SysError) {RepTag (X,BOTTOM); return NULL;}
- } while (C);
- if (!Quoted) F->InPtr--;
- InBlanks (F);
- return X->String;
- }
-
-
- /*
- * InList
- *
- * Input a list
- *
- * Input
- * F = input descriptor pointing to first token after '<'
- *
- * Output
- * result = true iff no error occurs
- * *X = sequence, or unchanged if error occurs.
- */
- private boolean InList (F,X)
- register InDesc *F;
- ObjectPtr X;
- {
- ListPtr R=NULL;
- register MetaPtr A = &R;
-
- while (!IsTok (F,">")) {
- if (!*F->InPtr) {
- DelLPtr (R);
- return InError (F,"unfinished sequence");
- }
- NewList (A,1L);
- if (SysError || !InObject (F,&(*A)->Val)) {
- DelLPtr (R);
- return 0;
- }
- A = & (*A)->Next;
- (void) IsTok (F,",");
- }
- RepTag (X,LIST);
- X->List = R;
- return 1;
- }
-
- /*
- * InObject
- *
- * Read an object.
- *
- * Input
- * *F = input descriptor pointing to object
- *
- * Output
- * *F = input descriptor pointing to next token
- * result = true iff object is read successfully.
- *
- * A SysError may occur, in which case X is unchanged.
- */
- boolean InObject (F,X)
- register InDesc *F;
- register ObjectPtr X;
- {
- if (IsTok (F,"<")) return InList (F,X);
-
- else if (IsTok (F,"(")) {
-
- (void) InComp (F,X,NIL);
- if (!IsTok (F,")")) return InError (F,"')' expected");
-
- } else {
-
- /* Input atom */
-
- static char Delim[2] = {'\0','\0'};
- *Delim = *F->InPtr;
-
- if (*Delim == '\"' || *Delim == '\'') {
- F->InPtr++;
- (void) InString (F,X,Delim,1);
- } else {
-
- FPint K;
- register StrPtr S = InString (F,X,ObDelim,0);
- if (S == NULL) return SysError || InError (F,"object expected");
- if (S->StrChar[1] == '\0')
- switch (S->StrChar[0]) {
- case 'f':
- RepBool (X,0);
- return 1;
- case 't':
- RepBool (X,1);
- return 1;
- case '?':
- RepTag (X,BOTTOM);
- return 1;
- }
- if (StrToFloat (X) && !GetFPInt (X,&K)) {
- X->Tag = INT;
- X->Int = K;
- }
- }
- }
- return 1;
- }
-
- /*
- * InitIn
- *
- * Initialize input descriptor for node N and file FileDesc.
- * Advance the input pointer to the first token.
- *
- * Input
- * *F = input descriptor
- * M = module pointer
- * FileDesc = open file descriptor
- * LineNum = 0 for normal input, -1 if single-line mode
- */
- void InitIn (F,M,FileDesc,LineNum)
- register InDesc *F;
- NodePtr M;
- FILE *FileDesc;
- int LineNum;
- {
- F->InFile = FileDesc;
- F->InLineNum= LineNum;
- F->InPtr = F->InBuf;
- *F->InPtr = '\0';
- F->InDefMod = M;
- F->ComLevel = 0;
- InBlanks (F);
- }
-
-
- /******************************* end of inob.c *******************************/
-
- SHAR_EOF
- if test -f 'interp/inob.h'
- then
- echo shar: over-writing existing file "'interp/inob.h'"
- fi
- cat << \SHAR_EOF > 'interp/inob.h'
-
- /****** inob.h ********************************************************/
- /** **/
- /** University of Illinois **/
- /** **/
- /** Department of Computer Science **/
- /** **/
- /** Tool: IFP Version: 0.5 **/
- /** **/
- /** Author: Arch D. Robison Date: May 1, 1985 **/
- /** **/
- /** Revised by: Arch D. Robison Date: Sept 9, 1986 **/
- /** **/
- /** Principal Investigators: Prof. R. H. Campbell **/
- /** Prof. W. J. Kubitz **/
- /** **/
- /** **/
- /**------------------------------------------------------------------**/
- /** (C) Copyright 1987 University of Illinois Board of Trustees **/
- /** All Rights Reserved. **/
- /**********************************************************************/
-
- #define INBUFSIZE 255 /* 65 <= INBUFSIZE <= 255 for DOS */
-
- /*
- * InDesc
- *
- * Input descriptor.
- *
- * Currently, there are three forms of IFP input:
- *
- * 1. Definition files
- * 2. Import files
- * 3. Terminal input
- *
- * All three forms are managed by input descriptors. An input descriptor
- * buffers the file, and keeps track of context (e.g. line number).
- */
-
- typedef struct {
- char *InPtr; /* Pointer to current character being scanned */
- int InLineNum; /* Line number of line being read [1] */
- int ComLevel; /* Current comment nesting level [2] */
- NodePtr InDefMod; /* Module node of current definition being read */
- StrPtr InDefFun; /* Name of current definition */
- FILE *InFile; /* File descriptor of file being read */
- char InBuf[INBUFSIZE]; /* Buffer for current line being scanned */
- } InDesc;
-
- /*
- * Footnotes
- *
- * [1] A line number of -1 indicates unnumbered lines, i.e. terminal input.
- *
- * [2] ComLevel should always be zero outside of function "InBlanks".
- * A non-zero value indicates an "open comment" error.
- */
-
- extern StrPtr InString ();
- extern char NodeDelim[];
-
- /******************************* end of inob.h *******************************/
-
- SHAR_EOF
- if test -f 'interp/list.c'
- then
- echo shar: over-writing existing file "'interp/list.c'"
- fi
- cat << \SHAR_EOF > 'interp/list.c'
-
- /****** list.c ********************************************************/
- /** **/
- /** University of Illinois **/
- /** **/
- /** Department of Computer Science **/
- /** **/
- /** Tool: IFP Version: 0.5 **/
- /** **/
- /** Author: Arch D. Robison Date: May 1, 1985 **/
- /** **/
- /** Revised by: Arch D. Robison Date: Jan 15, 1986 **/
- /** **/
- /** Principal Investigators: Prof. R. H. Campbell **/
- /** Prof. W. J. Kubitz **/
- /** **/
- /** **/
- /**------------------------------------------------------------------**/
- /** (C) Copyright 1987 University of Illinois Board of Trustees **/
- /** All Rights Reserved. **/
- /**********************************************************************/
-
- #include <stdio.h>
- #include "struct.h"
- #include "node.h"
- #include "umax.h"
- #include "string.h"
- #include "stats.h"
-
- /*
- * FreeList
- *
- * ListCells in free-list always contain:
- *
- * LRef == LRefOne
- * Val.Tag == BOTTOM
- * Next == pointer to next cell in free list.
- */
- ListPtr FreeList = NULL;
- #define LRefAdd(P,Delta) ((P)->LRef+=(Delta))
-
- /*************** Fundamental List Manipulation Routines ***************/
-
- private ListPtr FixCopyLPtr (); /* forward reference */
-
- /*
- * Rot3
- */
- void Rot3 (A,B,C)
- MetaPtr A,B,C;
- {
- register ListPtr P;
- P = *A; *A = *B; *B = *C; *C = P;
- }
-
- /*
- * ListLength
- *
- * Input
- * P = pointer to list
- *
- * Output
- * result = length of list
- */
- long ListLength (P)
- register ListPtr P;
- {
- register long N;
- for (N=0; P!=NULL; P=P->Next) N++;
- return N;
- }
-
- /*
- * CopyObject
- *
- * Copy object: X := Y
- *
- * A SysError may occur.
- */
- void CopyObject (X,Y)
- ObjectPtr X,Y;
- {
- register ListPtr P;
-
- switch (X->Tag = Y->Tag) {
- case BOTTOM: break;
- case BOOLEAN: X->Bool = Y->Bool; break;
- case INT: X->Int = Y->Int; break;
- case FLOAT: X->Float = Y->Float; break;
- case LIST:
- /* CopyLPtr expanded inline for speed */
- P = Y->List;
- if (P!=NULL && LRefAdd (P,1) == LRefOne-1)
- /*
- * This won't work for multiprocessor version
- * since other processors will not detect overflow.
- */
- P = FixCopyLPtr (P);
- X->List = P;
- break;
- case STRING: X->String = CopySPtr (Y->String); break;
- case NODE: X->Node = CopyNPtr (Y->Node); break;
- }
- }
-
- /*
- * NewList
- *
- * Point *A to list of N cells with last cell's Next set to old value of *A.
- *
- * Each cell value is set to BOTTOM
- *
- * A SysError may occur, in which case *A remains unchanged.
- *
- * Implementation note:
- * (x >= 0) is faster than (x > 0) on 16-bit machines since only
- * the sign bit must be checked.
- */
- void NewList (A,N)
- MetaPtr A;
- register long N;
- {
- extern ListPtr AllocListPage ();
- register MetaPtr B;
- ListPtr P;
-
- Stat (StatNewList (N));
- if (--N >= 0) {
- B = &FreeList;
- do {
- if (*B == NULL && (*B = AllocListPage ()) == NULL) {
- SysError = NO_LIST_FREE;
- printf ("NO MORE LIST CELLS LEFT\n");
- return;
- }
- B = &(*B)->Next;
- } while (--N >= 0);
- P = FreeList;
- FreeList = *B;
- *B = *A;
- *A = P;
- }
- }
-
- /*
- * Repeat
- *
- * Create a new list containing N copies of an object
- *
- * Output
- * result = pointer to list
- *
- * A SysError may occur, in which case NULL is returned.
- */
- ListPtr Repeat (X,N)
- register ObjectPtr X;
- long N;
- {
- ListPtr P=NULL;
- register ListPtr Q;
-
- NewList (&P,N);
- if (!SysError)
- for (Q=P; Q!=NULL; Q=Q->Next)
- CopyObject (&Q->Val,X);
- return P;
- }
-
- /*
- * DelLPtr
- *
- * Delete a list pointer: decrement reference count and return to free-list
- * if not used anymore.
- *
- * Routine is "vectorized" in that it is optimized to return long lists
- * to the freelist.
- */
- void DelLPtr (P)
- register ListPtr P;
- {
- register ListPtr Q,R;
-
- Stat (StatDelLPtr (P));
-
- for (R=P; R!=NULL; R=R->Next) {
- if (R->LRef != LRefOne) {
- R->LRef--;
- break;
- }
- if (!Scalar (R->Val.Tag)) {
- switch (R->Val.Tag) {
- case LIST: DelLPtr (R->Val.List); break;
- case STRING: DelSPtr (R->Val.String); break;
- case NODE: DelNPtr (R->Val.Node); break;
- }
- R->Val.Tag = BOTTOM;
- }
- Q = R;
- }
- if (R != P) {
- Q->Next = FreeList;
- FreeList = P;
- }
- }
-
- /*
- * CopyLPtr
- *
- * Make a copy of a list pointer, incrementing the reference count.
- * If the reference count would overflow, a new list cell is generated.
- *
- * A SysError may occur, in which case the result is NULL.
- */
- ListPtr CopyLPtr (P)
- ListPtr P;
- {
- if (P!=NULL) {
- if (LRefAdd (P,1) == LRefOne-1) {
- return FixCopyLPtr (P);
- }
- }
- return P;
- }
-
- /*
- * FixCopyLPtr
- *
- * Copy a list pointer which overflowed.
- *
- * Input
- * P = pointer to list cell
- */
- private ListPtr FixCopyLPtr (P)
- ListPtr P;
- {
- ListPtr Q; /* Reference count overflowed */
-
- LRefAdd (P,-1);
- Q = CopyLPtr (P->Next);
- if (SysError) return NULL;
- NewList (&Q,1L);
- if (SysError) return NULL;
- CopyObject (&Q->Val,&P->Val);
- return Q;
- }
-
- /*
- * RepTag
- *
- * Replace an object tag with another tag.
- */
- void RepTag (Dest,NewTag)
- ObjectPtr Dest;
- char NewTag;
- {
- switch (Dest->Tag) {
- case LIST: DelLPtr (Dest->List); break;
- case STRING: DelSPtr (Dest->String); break;
- case NODE: DelNPtr (Dest->Node); break;
- /* default: break; */
- }
- Dest->Tag = NewTag;
- }
-
- /*
- * RepBool
- *
- * Replace an object with a boolean object
- */
- void RepBool (Dest,Value)
- ObjectPtr Dest;
- boolean Value;
- {
- RepTag (Dest,BOOLEAN);
- Dest->Bool = Value;
- }
-
- /*
- * RepObject
- *
- * Replace an Object by another Object.
- *
- * A SysError may occur.
- */
- boolean RepObject (Y,X)
- register ObjectPtr Y,X;
- {
- Object Z;
-
- switch (Z.Tag = Y->Tag) {
- case LIST: Z.List = Y->List; break;
- case STRING: Z.String = Y->String; break;
- case NODE: Z.Node = Y->Node; break;
- }
- switch (Y->Tag = X->Tag) {
- case BOTTOM: break;
- case BOOLEAN: Y->Bool = X->Bool; break;
- case INT: Y->Int = X->Int; break;
- case FLOAT: Y->Float = X->Float; break;
- case LIST: Y->List = CopyLPtr (X->List); break;
- case STRING: Y->String = CopySPtr (X->String); break;
- case NODE: Y->Node = CopyNPtr (X->Node); break;
- }
- switch (Z.Tag) {
- case LIST: DelLPtr (Z.List); break;
- case STRING: DelSPtr (Z.String); break;
- case NODE: DelNPtr (Z.Node); break;
- }
- }
-
-
- /*
- * RepLPtr
- *
- * Replace pointer variable *A by value B.
- *
- * A SysError may occur, in which case *A remains unchanged.
- */
- void RepLPtr (A,P)
- MetaPtr A;
- ListPtr P;
- {
- P = CopyLPtr (P); /* Copy P first so DelLPtr can't trash *P */
- if (SysError) return;
- DelLPtr (*A);
- *A = P;
- }
-
-
- /*
- * MakeCopy
- *
- * Make a copy of a non-empty list.
- *
- * Input
- * P = pointer to list
- *
- * Output
- * *A = pointer to identical list with LRef == LRefOne
- * result = metapointer to Next field of end of result list
- *
- * A SysError may occur, in which case *A remains unchanged.
- *
- * All sublist-head reference-counts are incremented if no error occurs.
- */
- MetaPtr MakeCopy (A,P)
- register ListPtr *A,P;
- {
- register ListPtr Q;
- ListPtr R=NULL; /* R = root of new list */
-
- NewList (&R,ListLength (P));
- if (SysError) return NULL;
-
- Q = R;
- while (1) {
- if (Scalar (P->Val.Tag)) {
- Q->Val.Data = P->Val.Data;
- Q->Val.Tag = P->Val.Tag;
- } else {
- CopyObject (& Q->Val,& P->Val);
- if (SysError) {DelLPtr (R); return NULL;};
- }
- P = P->Next;
- if (P == NULL) break;
- Q = Q->Next;
- };
-
- *A = R;
- return &Q->Next;
- }
-
-
- /*
- * CopyTop
- *
- * Replace *A with a pointer to a fresh (top level) copy of *A.
- *
- * Input
- * *A = pointer to list
- * Output
- * *A = pointer to identical list with LRef == LRefOne for top level
- *
- * A SysError may occur, in which case *A remains unchanged.
- */
- void CopyTop (A)
- register MetaPtr A;
- {
- register ListPtr P;
-
- while (1) { /* Search for shared part of list */
- P = *A;
- if (P == NULL) return;
- if (P->LRef != LRefOne) break;
- Stat (StatRecycle++);
- A = & P->Next;
- }
-
- (void) MakeCopy (A,P);
- P->LRef--;
- if (SysError) (*A)->LRef++;
- }
-
-
- /*
- * Copy2Top
- *
- * Replace *A with a pointer to a fresh (top 2 levels) of *A.
- *
- * Input
- * *A = pointer to list
- * Output
- * *A = pointer to identical list with LRef == LRefOne
- * for both top level and any immediate sublists.
- *
- * A SysError may occur, in which case *A remains unchanged.
- */
- void Copy2Top (A)
- register MetaPtr A;
- {
- register ListPtr P;
-
- while (1) { /* Search for shared part of list */
- P = *A;
- if (P == NULL) return;
- if (P->LRef != LRefOne) break;
- if (P->Val.Tag == LIST) {
- CopyTop (&P->Val.List);
- if (SysError) return;
- }
- Stat (StatRecycle++);
- A = & P->Next;
- }
-
- /* (*A) now points to shared list */
-
- (void) MakeCopy (A,(P = *A));
-
- if (SysError) return;
- P->LRef--;
- P = *A;
-
- do
- if (P->Val.Tag == LIST && *(A = &P->Val.List) != NULL) {
- /*
- * There must some more elegant way to efficiently merge these
- * two cases.
- */
- (*A)->LRef--; /* will be incremented by MakeCopy */
- (void) MakeCopy (A,*A);
- if (SysError) return;
- }
- while ((P=P->Next) != NULL);
- }
-
-
- /****************************** end of list.c ******************************/
-
- SHAR_EOF
- if test -f 'interp/main.c'
- then
- echo shar: over-writing existing file "'interp/main.c'"
- fi
- cat << \SHAR_EOF > 'interp/main.c'
-
- /****** main.c ********************************************************/
- /** **/
- /** University of Illinois **/
- /** **/
- /** Department of Computer Science **/
- /** **/
- /** Tool: IFP Version: 0.5 **/
- /** **/
- /** Author: Arch D. Robison Date: May 1, 1985 **/
- /** **/
- /** Revised by: Arch D. Robison Date: Jan 20, 1987 **/
- /** **/
- /** Principal Investigators: Prof. R. H. Campbell **/
- /** Prof. W. J. Kubitz **/
- /** **/
- /** **/
- /**------------------------------------------------------------------**/
- /** (C) Copyright 1987 University of Illinois Board of Trustees **/
- /** All Rights Reserved. **/
- /**********************************************************************/
-
- #include <stdio.h>
- #include "struct.h"
- #include "node.h"
- #include "umax.h"
- #include "cache.h"
- #include "stats.h"
-
- #if OPSYS!=CTSS
- #endif
-
- static char Version[] = "\nIllinois FP 0.5";
- static char Author [] = " Arch D. Robison";
- static char Date [] = " Dec 5, 1986\n";
-
- #if OPSYS==UNIX
- #define OPSYSTEM "UNIX"
- #endif
- #if OPSYS==MSDOS
- #define OPSYSTEM "MS-DOS"
- #endif
- #if OPSYS==CTSS
- #define OPSYSTEM "CTSS"
- #endif
-
- boolean LongPathFlag = 0;
-
- #ifdef COMPILE
- boolean CompilerFlag = 0; /* Enable compiler if set */
- boolean RuleFlag = 0; /* Display rules if set */
- #endif
-
- private void Init ()
- {
- extern void D_arith (), D_form (), D_pred (), D_misc (), D_seq (),
- D_ss (), D_subseq (), D_string (), D_cray (), D_vector ();
- extern void InitString (), InitNode (), InitFile ();
- extern char RootPath[]; /* from file.c */
- #if OPSYS==MSDOS
- char CWD [64];
- #endif
- #if OPSYS==UNIX
- extern void EnvGet ();
- #endif
- if (Debug & DebugInit) printf ("enter Init\n");
-
- InitString ();
- #if OPSYS==MSDOS
- CWDGet (CWD,MAXPATH);
- #endif
- #if OPSYS==UNIX
- EnvGet ("IFProot",RootPath,MAXPATH); /* Check for RootPath */
- #endif
- #if ECACHE
- InitCache ();
- #endif
-
- InitNode ();
- D_arith ();
- D_form ();
- D_pred ();
- D_seq ();
- D_subseq ();
- D_misc ();
- D_ss ();
- D_string ();
- #if OPSYS==MSDOS
- InitFile (CWD);
- #endif
- #if OPSYS==UNIX || OPSYS==CTSS
- InitFile ();
- #endif
- #ifdef COMPILE
- if (CompilerFlag) {
- extern void InitSymTab (), InitCompiler ();
- InitSymTab ();
- InitCompiler ();
- }
- #endif
- #ifdef GRAPHICS
- InitDraw (); /* for CS9000 graphics only */
- #endif
- #if STATS
- printf (" (stats)");
- #endif
- if (Debug & DebugInit) printf ("exit Init\n");
- }
-
- extern void UserLoop ();
-
- /*
- * GetOptions
- *
- * Process command line options.
- *
- * Input
- * argv = command line arguments
- * argc = argument count
- */
- private void GetOptions (argc,argv)
- int argc;
- char *argv[];
- {
- int k;
- char *P;
-
- for (k=1; k<argc; k++)
- if (*(P=argv[k]) == '-')
- while (*P && *++P)
- switch (*P) {
- #ifdef COMPILE
- case 'c': CompilerFlag = 1; break;
- case 'r': RuleFlag = 1; break;
- #endif
- #if DEBUG
- case 'd':
- while (*++P) {
- extern char *index();
- static char Opt[] = DebugOpt;
- char *t = index (Opt,*P);
- if (t != NULL) Debug |= 1 << (t-Opt);
- else printf ("[unknown option = -d%c] ",*P);
- }
- break;
- #endif /* DEBUG */
- #if ECACHE
- case 'e':
- while (*++P)
- if (*P >= '0' && *P <= '2')
- Cache[*P-'0'].Enable = 1;
- else
- printf ("[unknown -e option = %c] ",*P);
- break;
- #endif /* ECACHE */
- case 'l': LongPathFlag = 1; break;
- default:
- printf ("[unknown option = %c] ",*P);
- P = "";
- break;
- }
- }
-
- main (argc, argv)
- int argc;
- char *argv[];
- {
- printf ("%s: (%s)",Version,OPSYSTEM);
- (void) fflush (stdout);
- GetOptions (argc,argv);
- Init ();
- printf ("\n\n");
- UserLoop ();
- Terminate();
- if (Debug & DebugInit) printf ("normal exit\n");
- exit (0);
- }
-
- /************************** end of main.c **************************/
-
- SHAR_EOF
- if test -f 'interp/node.c'
- then
- echo shar: over-writing existing file "'interp/node.c'"
- fi
- cat << \SHAR_EOF > 'interp/node.c'
-
- /****** node.c ********************************************************/
- /** **/
- /** University of Illinois **/
- /** **/
- /** Department of Computer Science **/
- /** **/
- /** Tool: IFP Version: 0.5 **/
- /** **/
- /** Author: Arch D. Robison Date: May 1, 1985 **/
- /** **/
- /** Revised by: Arch D. Robison Date: Nov 23, 1985 **/
- /** **/
- /** Principal Investigators: Prof. R. H. Campbell **/
- /** Prof. W. J. Kubitz **/
- /** **/
- /** **/
- /**------------------------------------------------------------------**/
- /** (C) Copyright 1987 University of Illinois Board of Trustees **/
- /** All Rights Reserved. **/
- /**********************************************************************/
-
- #include <stdio.h>
- #include "struct.h"
- #include "node.h"
- #include "umax.h"
- #include "string.h"
-
- /********************************* NODE RULES ******************************
-
- Function definitions are stored in nodes, which are arranged in a tree
- structure mimicking the UNIX file structure. Below is an example:
-
- Rm
- |
- Am---Bi----Cm-------Dd
- | |
- Xd Yd--Zd
-
- Rm is the root node, with children Am,Bi,Cm, and Dd. Nodes can be one of three
- types: module (m), import (i), or definition (d). Only definition nodes
- have a reference count greater than 1. Only module nodes have children.
-
- ****************************** end of node rules **************************/
-
- NodePtr RootNode,SysNode,LogicNode,ArithNode;
-
- /* Free nodes have NREF == 0 and are linked by NodeSib field */
- NodePtr FreeNode = NULL;
-
- /*
- * DelNPtr
- *
- * Note: node pointers always have a parent pointer to them, so
- * we don't have to delete them here.
- *
- * Input
- * N = pointer to node
- */
- void DelNPtr (N)
- NodePtr N;
- {
- rsemaphore_enter (NRefSemaphore);
- if (N != NULL) N->NRef--;
- rsemaphore_exit (NRefSemaphore);
- }
-
-
- /*
- * CopyNPtr
- */
- NodePtr CopyNPtr (N)
- NodePtr N;
- {
- rsemaphore_enter (NRefSemaphore);
- if (N != NULL && !++N->NRef) IntError ("CopyNPtr: too many refs");
- rsemaphore_exit (NRefSemaphore);
- return N;
- }
-
-
- /*
- * NewNode
- *
- * Point *N to new node from free list. The input value of *N is
- * put in the NodeSib field of the new node.
- *
- * A SysError may occur, in which case *N is unchanged.
- */
- private void NewNode (N)
- NodePtr *N;
- {
- extern NodePtr AllocNodePage ();
- register NodePtr T;
-
- rsemaphore_enter (NRefSemaphore);
- if (FreeNode == NULL && (FreeNode = AllocNodePage ()) == NULL) {
- printf ("NO MORE NODE CELLS LEFT\n");
- SysError = NO_NODE_FREE;
- } else {
- T = FreeNode;
- FreeNode = FreeNode->NodeSib;
- T->NodeSib = *N;
- *N = T;
- }
- rsemaphore_exit (NRefSemaphore);
- }
-
-
- /*
- * FindNode
- *
- * Find a node within a module with a specified name.
- *
- * Input
- * M = pointer to module node
- * S = pointer to string
- *
- * Output
- * result = NULL if node not found, pointer to node otherwise
- */
- NodePtr FindNode (M,S)
- register NodePtr M;
- StrPtr S;
- {
- if (M->NodeType == MODULE)
- for (M = M->NodeData.NodeMod.FirstChild; M!=NULL; M=M->NodeSib)
- if (0==StrComp (M->NodeName,S)) return M;
- return NULL;
- }
-
-
- /*
- * MakePath
- *
- * Make the path list for a given node
- *
- * Input
- * *N = module node
- * Output
- * *result = path list
- */
- ListPtr MakePath (N)
- NodePtr N;
- {
- ListPtr P;
-
- rsemaphore_enter (NRefSemaphore);
- P = NULL;
- while (N->NodeParent != NULL) {
- NewList (&P,1L);
- P->Val.Tag = STRING;
- P->Val.String = CopySPtr (N->NodeName);
- N = N->NodeParent;
- }
- rsemaphore_exit (NRefSemaphore);
- return P;
- }
-
-
- /*
- * MakeChild
- *
- * Find (or create if necessary) a new child node with a specified name.
- *
- * Input
- * M = Parent node
- * S = name of child
- *
- * Output
- * N = pointer to child
- *
- * A SysError may occur.
- */
- NodePtr MakeChild (M,S)
- NodePtr M;
- StrPtr S;
- {
- register NodePtr N;
-
- rsemaphore_enter (NRefSemaphore);
- N = FindNode (M,S);
- if (N==NULL) {
- NewNode (&M->NodeData.NodeMod.FirstChild);
- if (SysError) {
- N = NULL;
- goto exit;
- }
- N = M->NodeData.NodeMod.FirstChild;
- N->NodeParent = M;
- N->NodeName = CopySPtr (S);
- N->NodeType = NEWNODE;
- }
- exit:
- rsemaphore_exit (NRefSemaphore);
- return N;
- }
-
- /*
- * Initialize a module node
- *
- * Input
- * M = pointer to new node
- */
- void InitModule (M)
- register NodePtr M;
- {
- M->NodeType = MODULE;
- M->NodeData.NodeMod.FirstChild = NULL;
- ReadImport (M);
- }
-
- /*
- * MakeNode
- *
- * Create all nodes required by a path.
- *
- * Input
- * Path = pointer to path list
- * Type = type to make node if new node
- * Output
- * result = pointer to node specified by path or
- * NULL if an error occurred.
- */
- NodePtr MakeNode (Path,Type)
- ListPtr Path;
- int Type;
- {
- register NodePtr M;
- register ListPtr P;
-
- rsemaphore_enter (NRefSemaphore);
- M = RootNode;
- for (P=Path; P != NULL; P=P->Next)
- if (P->Val.Tag != STRING) return NULL;
- else {
- M = MakeChild (M,P->Val.String);
- if (M->NodeType == NEWNODE)
- if (P->Next!=NULL) InitModule (M);
- else
- switch (M->NodeType = Type) {
- case DEF:
- M->NodeData.NodeDef.DefCode.Tag = BOTTOM;
- M->NodeData.NodeDef.DefFlags = 0;
- break;
- case MODULE:
- InitModule (M);
- break;
- }
- }
- rsemaphore_exit (NRefSemaphore);
- return M;
- }
-
-
- /*
- * DelImport
- *
- * Delete all information affected by the %IMPORT file for a module node
- * in preparation for rereading the %IMPORT file.
- *
- * Input
- * M = pointer to module node
- *
- * Notes
- * IMPORT nodes can be returned to the free list since their
- * reference counts are always 1.
- */
- void DelImport (M)
- NodePtr M;
- {
- register NodePtr *L;
- register NodePtr N;
-
- rsemaphore_enter (NRefSemaphore);
- for (L = &M->NodeData.NodeMod.FirstChild; (N = *L)!= NULL; )
-
- switch (N->NodeType) {
-
- case IMPORT: /* Return IMPORT nodes to free list */
- DelSPtr (N->NodeName);
- RepTag (&N->NodeData.NodeImp.ImpDef,BOTTOM);
- Rot3 ((MetaPtr) &FreeNode, (MetaPtr) L, (MetaPtr) &N->NodeSib);
- break;
-
- case DEF: /* Delete local function definitions */
- if (N->NodeData.NodeDef.DefCode.Tag != CODE)
- RepTag (&N->NodeData.NodeDef.DefCode,BOTTOM);
- L = &N->NodeSib;
- break;
-
- case MODULE:
- L = &N->NodeSib;
- break;
-
- default:
- printf ("Invalid NodeType in node tree: %d\n",N->NodeType);
- L = &N->NodeSib;
- break;
- }
- rsemaphore_exit (NRefSemaphore);
- }
-
-
- /*
- * LinkPath
- *
- * Convert a path list to a node if possible.
- *
- * Input
- * *Def = path list
- * Type = NodeType value if new node
- *
- * Output
- * *Def = node or not changed if error occurs
- */
- void LinkPath (Path,Type)
- ObjectPtr Path;
- int Type;
- {
- register NodePtr N;
-
- rsemaphore_enter (NRefSemaphore);
- N = MakeNode (Path->List,Type);
- if (N != NULL) {
- RepTag (Path,NODE);
- Path->Node = CopyNPtr (N);
- }
- rsemaphore_exit (NRefSemaphore);
- }
-
- /*
- * SignExtend
- *
- * Sign extend a byte. Not all machines have signed characters.
- */
- #define SignExtend(B) ((((B) + 0x80) & 0xFF) - 0x80)
-
- /*
- * PrimDef
- *
- * Define a primitive function
- *
- * Input
- * *F = object code for function
- * S = name of function
- * M = module to put function in
- * K = code parameter value
- *
- * Output
- * result = pointer to node containing function
- */
- /* VARARGS3 */
- NodePtr PrimDef (F,S,M,K)
- int (*F) ();
- char *S;
- NodePtr M;
- char K;
- {
- register NodePtr N;
- StrPtr T;
- T = MakeString (S);
- N = MakeChild (M,T);
- N->NodeType = DEF;
- N->NodeData.NodeDef.DefCode.Tag = CODE;
- N->NodeData.NodeDef.DefFlags = 0;
- N->NodeData.NodeDef.DefCode.Code.CodePtr = F;
- N->NodeData.NodeDef.DefCode.Code.CodeParam = SignExtend (K);
- DelSPtr (T);
- return N;
- }
-
-
- /*
- * GroupDef
- *
- * Define a group of functions
- *
- * Input
- * T = pointer to table of functions
- * N = number entries in table
- * M = module node
- */
- void GroupDef (T,N,M)
- register OpDef *T;
- int N;
- NodePtr M;
- {
- while (--N >= 0)
- (void) PrimDef (T->OpPtr,T->OpName,M,T->OpParam),
- T++;
- }
-
-
- /*
- * Initialize root node and 'sys' subnode.
- */
- void InitNode ()
- {
- register NodePtr R;
-
- if (Debug & DebugInit) printf ("enter InitNode\n");
- RootNode = NULL;
- NewNode (&RootNode);
- R = RootNode;
- R->NodeSib = NULL;
- R->NodeParent = NULL;
- R->NodeType = MODULE;
- R->NodeName = MakeString ("ROOT");
- R->NodeData.NodeMod.FirstChild = NULL;
- SysNode = MakeChild (R,MakeString ("sys"));
- InitModule (SysNode);
- R = MakeChild (R,MakeString ("math"));
- InitModule (R);
- ArithNode = MakeChild (R,MakeString ("arith"));
- InitModule (ArithNode);
- LogicNode = MakeChild (R,MakeString ("logic"));
- InitModule (LogicNode);
- if (Debug & DebugInit) printf ("exit InitNode\n");
- }
-
- /****************************** end of node.c ******************************/
- SHAR_EOF
- if test -f 'interp/node.h'
- then
- echo shar: over-writing existing file "'interp/node.h'"
- fi
- cat << \SHAR_EOF > 'interp/node.h'
-
- /****** node.h ********************************************************/
- /** **/
- /** University of Illinois **/
- /** **/
- /** Department of Computer Science **/
- /** **/
- /** Tool: IFP Version: 0.5 **/
- /** **/
- /** Author: Arch D. Robison Date: May 1, 1985 **/
- /** **/
- /** Revised by: Arch D. Robison Date: July 8, 1986 **/
- /** **/
- /** Principal Investigators: Prof. R. H. Campbell **/
- /** Prof. W. J. Kubitz **/
- /** **/
- /** **/
- /**------------------------------------------------------------------**/
- /** (C) Copyright 1987 University of Illinois Board of Trustees **/
- /** All Rights Reserved. **/
- /**********************************************************************/
-
- #ifndef INCLUDE_NODE_H
- #define INCLUDE_NODE_H 1
-
- /*
- * Define FETCH as 1 to define "fetch" (^k) functional form, 0 otherwise.
- * Define XDEF as 1 to define "xdef" ({...} f) functional form, 0 otherwise.
- */
- #define FETCH 0
- #define XDEF 1
-
- extern ListPtr MakePath ();
- extern NodePtr CopyNPtr (), FindNode ();
- extern NodePtr MakeNode (), MakeChild (), PrimDef ();
- extern NodePtr RootNode, SysNode, ArithNode, LogicNode;
- extern void DelNPtr (), FormPath (), GroupDef (), LinkPath ();
- void InitNode ();
-
- typedef struct { /* Used for node initialization tables */
- char *OpName;
- char OpParam;
- int (*OpPtr) (); /* Actually void, but compiler complains about void */
- } OpDef; /* in static initializations of this structure */
-
- #define OpCount(OpTable) (sizeof(OpTable)/sizeof(OpTable[0]))
-
- extern NodePtr FormNode[];
-
- /*
- * Subscripts for FormNode
- *
- * These must correspond to the entries in the FormOpTable in forms.c
- */
- #define NODE_C 0
- #define NODE_Comp 1
- #define NODE_Cons 2
- #define NODE_Each 3
- #define NODE_Fetch 4
- #define NODE_Filter (4 + FETCH)
- #define NODE_If (5 + FETCH)
- #define NODE_RInsert (6 + FETCH)
- #define NODE_Out (7 + FETCH)
- #define NODE_Sel (8 + FETCH)
- #define NODE_While (9 + FETCH)
- #define NODE_XDef (9 + FETCH + XDEF)
- #define FORM_TABLE_SIZE (10 + FETCH + XDEF)
-
-
- typedef struct {
- NodePtr FormNode; /* Node pointer for form */
- char *FormInPrefix;
- OpDef FormOp;
- char *FormComment; /* Comment for `expected' error message */
- } FormEntry;
-
- extern FormEntry FormTable[FORM_TABLE_SIZE];
-
- #endif
-
- /****************************** end of node.h ******************************/
-
- SHAR_EOF
- # End of shell archive
- exit 0
-
- --
-
- Rich $alz "Anger is an energy"
- Cronus Project, BBN Labs rsalz@pineapple.bbn.com
- Moderator, comp.sources.unix sources@uunet.uu.net
-